package com.punai.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.punai.common.constant.UserConstants;
import com.punai.common.constant.VerifyAccountConstants;
import com.punai.common.core.domain.entity.SysDept;
import com.punai.common.core.domain.entity.SysUser;
import com.punai.common.exception.ServiceException;
import com.punai.common.properties.FileUpPathConfig;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.excel.ExcelListener;
import com.punai.file.domain.FileUploadFile;
import com.punai.file.mapper.FileUploadFileMapper;
import com.punai.system.bo.ep.DepartmentOfWeChat;
import com.punai.system.bo.ep.UserOfDept;
import com.punai.system.bo.ep.UserOfWeChat;
import com.punai.system.bo.ep.UserWxExcel;
import com.punai.system.mapper.SysDeptMapper;
import com.punai.system.mapper.SysUserMapper;
import com.punai.system.service.EpWxService;
import com.punai.system.util.WeChatComUtil;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class EpWxServiceImpl implements EpWxService {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private WeChatComUtil weChatComUtil;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;

    private Boolean isProcess = false;

    @Autowired
    private FileUploadFileMapper uploadFileMapper;

    @Override
    public boolean syncUser(Long companyId) {
        List<Map<String, Object>> allUser = new ArrayList<>();

        allUser = weChatComUtil.getAllUser(null, allUser);
        logger.info("allUser:Size" + allUser.size());
    /*
        List<UserOfWeChat> result = new ArrayList<>();
        for (Map<String, Object> hashMap : allUser) {
            String userid = Convert.toStr(hashMap.get("userid"));
            String departments = Convert.toStr(hashMap.get("department"));
            UserOfWeChat userInfo = weChatComUtil.getUserInfo(userid);
            userInfo.setDepartments(departments);
            result.add(userInfo);
        }
        logger.info("resultList:Size" + result.size());
        logger.info("resultList:List" + JSONUtil.toJsonStr(result));
*/
        try {
            List<String> wxUserIds = allUser.stream().map(e -> Convert.toStr(e.get("userid"))).collect(Collectors.toList());
            Map<String, SysUser> userMap = findByWeChatComUserids(wxUserIds, companyId);

            List<String> wxDepartments = allUser.stream().map(e -> Convert.toStr(e.get("department"))).collect(Collectors.toList());

            Set<String> realDeps = new HashSet<>();
            for (String department : wxDepartments) {
                List<String> deps = Arrays.asList(department.split(","));
                realDeps.addAll(deps);
            }

            Map<String, SysDept> deptMap = findByWeChatComDepids(realDeps, companyId);

            if (deptMap.size() != realDeps.size()) {
                throw new ServiceException("用户的父级部门未同步，请先在部门管理中同步部门！");
            }

            logger.info("deptMap-86:" + JSONUtil.toJsonStr(deptMap));
            logger.info("userMap-87:" + JSONUtil.toJsonStr(userMap));

            for (Map<String, Object> v : allUser) {
                boolean isInsert = false;
                String department = Convert.toStr(v.get("department"));
                String userid = Convert.toStr(v.get("userid"));
                SysUser user = userMap.get(userid);
                if (user == null) {
                    user = new SysUser();
                    isInsert = true;
                }
                List<String> deps = Arrays.asList(department.split(","));
                // List<Long> departments = new ArrayList<>();
                for (String dep : deps) {
                    SysDept comDepid = deptMap.get(dep);
                    // departments.add(comDepid.getDeptId());
                    user.setDeptId(comDepid.getDeptId());
                }
                user.setWeChatComUserid(userid);
                user.setEmail(userid + "_WeCaht@ty.com");
                user.setNickName(userid + "_WeCaht");

                logger.info("deptMap-112:" + JSONUtil.toJsonStr(deptMap));

                if (isInsert) {
                    user.setCompanyId(companyId);
                    user.setType(VerifyAccountConstants.ACCOUNT_TYPE.ZS.getCode());
                    user.setUsePlace(VerifyAccountConstants.ACCOUNT_PLACE.TY.getCode());
                    user.setUserName(userid);
                    user.setDelFlag(UserConstants.NORMAL);
                    user.setStatus(UserConstants.NORMAL);
                    String randomSalt = SecurityUtils.getRandomSalt();
                    user.setSalt(randomSalt);
                    user.setPassword(SecurityUtils.md5EncodePassword("tianyuan123" + randomSalt));
                    sysUserMapper.insert(user);
                } else {
                    sysUserMapper.update(user,
                            Wrappers.<SysUser>lambdaUpdate()
                                    .eq(SysUser::getUserId, user.getUserId())
                                    .eq(SysUser::getCompanyId, companyId)
                    );
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private Map<String, SysUser> findByWeChatComUserids(List<String> wxUserIds, Long companyId) {

        List<SysUser> sysUsers = sysUserMapper.selectList(
                Wrappers.<SysUser>lambdaQuery()
                        .in(SysUser::getWeChatComUserid, wxUserIds)
                        .eq(SysUser::getCompanyId, companyId)
        );
        return sysUsers.stream().collect(Collectors.toMap(SysUser::getWeChatComUserid, Function.identity(), (v1, v2) -> v2));
    }


    @Override
    public boolean syncDepartment(Long companyId) {
        isProcess = true;
        // 根据当前登录人的部门来同步部门下的用户
        // Long deptId = SecurityUtils.getDeptId();
        // SysDept sysDept = sysDeptMapper.selectById(deptId);
        // String weChatComDepId = sysDept.getWeChatComDepId();
        try{
            List<DepartmentOfWeChat> allDepartment = weChatComUtil.getAllDepartment(null);
            logger.info(JSONUtil.toJsonStr(allDepartment));
            ArrayListValuedHashMap<String, DepartmentOfWeChat> valuedHashMap = new ArrayListValuedHashMap<>();
            List<String> deptWxIds = new ArrayList<>();
            for (DepartmentOfWeChat map : allDepartment) {
                deptWxIds.add(map.getId());
                String parentid = map.getParentid();
                valuedHashMap.put(parentid, map);
            }

            /**
             * 顶级部门 查询用户时不递归查询子部门用户
             */
            List<String> deptIdsLevel1 = new ArrayList<>();


            //
            Map<String, SysDept> sysDeptMap = findByWeChatComDepids(deptWxIds, companyId);
            List<DepartmentOfWeChat> roots = valuedHashMap.get("0");
            int orderNum = 0;
            for (DepartmentOfWeChat root : roots) {
                deptIdsLevel1.add(root.getId());
                SysDept one = new SysDept();
                SysDept byWeChatComDepid = sysDeptMap.get(root.getId());
                boolean isUpdate = false;
                if (byWeChatComDepid != null) {
                    one = byWeChatComDepid;
                    isUpdate = true;
                }
                one.setParentId(0L);
                one.setWeChatComDepId(root.getId());
                one.setWeChatComDepPid(root.getParentid());
                one.setDeptName(root.getName());
                one.setCompanyId(companyId);
                one.setAncestors("0");
                one.setDelFlag("0");
                one.setStatus("0");
                orderNum++;
                one.setOrderNum(Convert.toInt(root.getOrder(), orderNum));
                if (isUpdate) {
                    sysDeptMapper.updateDept(one);
                } else {
                    sysDeptMapper.insert(one);
                }
                syncDepartmentGetChildren(one, valuedHashMap, sysDeptMap, companyId);

                /**
                 * 顶级部门
                 */
                for (String deptId : deptIdsLevel1) {
                    getDeptUsers(deptId, 0,sysDeptMap);
                }
                /**
                 * 二级部门 查询用户时需要递归查询子部门用户
                 */
                List<DepartmentOfWeChat> rootLevel2s = valuedHashMap.get(one.getWeChatComDepId());
                for (DepartmentOfWeChat rootLevel2 : rootLevel2s) {
                    String id = rootLevel2.getId();
                    getDeptUsers(id, 1,sysDeptMap);
                }
            }
            isProcess = false;
        }catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }finally {
            isProcess = false;
        }
        return true;
    }

    @Autowired
    private FileUpPathConfig fileUpPathConfig;

    @Override
    public String refreshUserInfo(String fileId) {
        FileUploadFile uploadFile = uploadFileMapper.selectById(fileId);
        String filePath = uploadFile.getFilePath();
        InputStream inputStream = FileUtil.getInputStream(fileUpPathConfig.getBasePath() + filePath);
        if (inputStream == null) {
            throw new ServiceException("对应文件不存在,请联系管理员");
        }
        //监视器
        ExcelListener<UserWxExcel> listener = new ExcelListener<>();
        ExcelReader excelReader = EasyExcel.read(inputStream, listener).build();
        // 第一个sheet读取类型
        ReadSheet userListSheet = EasyExcel.readSheet("成员列表").head(UserWxExcel.class).headRowNumber(10).build();
        excelReader.read(userListSheet);
        List<UserWxExcel> userWxExcels = listener.getDataList();
        Map<String, UserWxExcel> userWxExcelMap = new HashMap<>();
        List<String> userWxIds = new ArrayList<>();
        for (UserWxExcel userWxExcel : userWxExcels) {
            userWxExcelMap.put(userWxExcel.getUserId(), userWxExcel);
            userWxIds.add(userWxExcel.getUserId());
        }

        List<SysUser> sysUsers = sysUserMapper.selectList(
                Wrappers.<SysUser>lambdaQuery()
                        .select(SysUser::getUserId, SysUser::getDeptId)
                        .in(SysUser::getWeChatComUserid, userWxIds)
        );
        for (SysUser sysUser : sysUsers) {
            String weChatComUserid = sysUser.getWeChatComUserid();
            UserWxExcel userWxExcel = userWxExcelMap.get(weChatComUserid);

            sysUser.setNickName(userWxExcel.getUserName());
            // 0=男,1=女,2=未知
            sysUser.setSex(
                    StrUtil.equals("男", userWxExcel.getSex()) ?
                            "0" : StrUtil.equals("女", userWxExcel.getSex()) ? "1" : "2"
            );

            sysUser.setPhonenumber(userWxExcel.getPhone());
            sysUser.setEmail(userWxExcel.getEmail());
        }
        return "成功";
    }

    @Override
    public boolean syncUserByDeptId() {
        isProcess = true;
        try {
            Long deptId = SecurityUtils.getDeptId();
            SysDept sysDept = sysDeptMapper.selectById(deptId);
            String weChatComDepId = sysDept.getWeChatComDepId();
            Map<String,SysDept> deptMap = new HashMap<>();
            deptMap.put(sysDept.getWeChatComDepId(),sysDept);
            List<SysDept> sysDepts = sysDeptMapper.selectChildrenDeptById(deptId);
            if (CollUtil.isNotEmpty(sysDepts)) {
                for (SysDept dept : sysDepts) {
                    deptMap.put(dept.getWeChatComDepId(),dept);
                }
            }
            getDeptUsers(weChatComDepId, 1,deptMap);
        }catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        } finally {
            isProcess = false;
        }
        return true;
    }

    @Override
    public boolean isProcess() {
        return isProcess;
    }

    private void syncDepartmentGetChildren(SysDept rootDep, ArrayListValuedHashMap<String, DepartmentOfWeChat> valuedHashMap,
                                           Map<String, SysDept> sysDeptMap, Long companyId) {
        List<DepartmentOfWeChat> roots = valuedHashMap.get(rootDep.getWeChatComDepId());
        int orderNum = 0;
        for (DepartmentOfWeChat root : roots) {
            SysDept one = new SysDept();
            SysDept byWeChatComDepid = sysDeptMap.get(root.getId());
            boolean isUpdate = false;
            if (byWeChatComDepid != null) {
                one = byWeChatComDepid;
                isUpdate = true;
            }
            one.setParentId(rootDep.getDeptId());
            one.setWeChatComDepId(root.getId());
            one.setWeChatComDepPid(root.getParentid());
            one.setDeptName(root.getName());
            one.setCompanyId(companyId);
            one.setAncestors(rootDep.getAncestors() + "," + rootDep.getDeptId());
            one.setDelFlag("0");
            one.setStatus("0");
            orderNum++;
            one.setOrderNum(Convert.toInt(root.getOrder(), orderNum));
            if (isUpdate) {
                sysDeptMapper.updateDept(one);
            } else {
                sysDeptMapper.insert(one);
            }
            syncDepartmentGetChildren(one, valuedHashMap, sysDeptMap, companyId);
        }

    }

    private Map<String, SysDept> findByWeChatComDepids(Collection<String> deptWxIds, Long companyId) {
        List<SysDept> sysDepts = sysDeptMapper.selectList(
                Wrappers.<SysDept>lambdaQuery()
                        .in(SysDept::getWeChatComDepId, deptWxIds)
                        .eq(SysDept::getCompanyId, companyId)
        );
        return sysDepts.stream().collect(Collectors.toMap(SysDept::getWeChatComDepId, Function.identity(), (v1, v2) -> v2));
    }


    private void getDeptUsers(String deptId, Integer isSelectChildUser,Map<String,SysDept> sysDeptMap) {
        List<UserOfDept> userOfDeptList = weChatComUtil.getUserOfDeptId(deptId, isSelectChildUser);
        if (CollUtil.isNotEmpty(userOfDeptList)) {
            List<String> wxUserIds = userOfDeptList.stream().map(e -> Convert.toStr(e.getUserid())).collect(Collectors.toList());
            Map<String, SysUser> userMap = findByWeChatComUserids(wxUserIds, 1L);

            for (UserOfDept v : userOfDeptList) {
                boolean isInsert = false;
                // List<String> department = v.getDepartment();
                String userid = v.getUserid();
                SysUser user = userMap.get(userid);
                if (user == null) {
                    user = new SysUser();
                    isInsert = true;
                }
                Long mainDepartment = v.getMain_department();
                SysDept sysDept = sysDeptMap.get(mainDepartment + "");
                if (sysDept != null) {
                    user.setDeptId(sysDept.getDeptId());
                }
                user.setWeChatComUserid(userid);
                user.setEmail(v.getEmail());
                user.setNickName(v.getName());
                // 企业微信定义 0表示未定义，1表示男性，2表示女性
                // 系统定义 0=男,1=女,2=未知

                String sex = "2";
                String gender = v.getGender();
                if (StrUtil.equals(gender, "1")) {
                    sex = "2";
                } else if (StrUtil.equals(gender, "2")) {
                    sex = "0";
                } else if (StrUtil.equals(gender, "3")) {
                    sex = "1";
                }
                user.setSex(sex);
                user.setStatus(v.getStatus() == 1 ? UserConstants.NORMAL : UserConstants.EXCEPTION);
                user.setAvatar(v.getAvatar());
                user.setPhonenumber(v.getMobile());

                if (isInsert) {
                    user.setCompanyId(1L);
                    user.setType(VerifyAccountConstants.ACCOUNT_TYPE.ZS.getCode());
                    user.setUsePlace(VerifyAccountConstants.ACCOUNT_PLACE.TY.getCode());
                    user.setUserName(userid);
                    user.setDelFlag(UserConstants.NORMAL);
                    // 系统定义 0正常 1停用
                    String randomSalt = SecurityUtils.getRandomSalt();
                    user.setSalt(randomSalt);
                    user.setPassword(SecurityUtils.md5EncodePassword("tianyuan123" + randomSalt));
                    sysUserMapper.insert(user);
                } else {
                    sysUserMapper.update(user,
                            Wrappers.<SysUser>lambdaUpdate()
                                    .eq(SysUser::getUserId, user.getUserId())
                                    .eq(SysUser::getCompanyId, 1L)
                    );
                }
            }
        }
    }


}
